from django.contrib import auth
from django.db.models import Q
from  rest_framework import serializers
from rest_framework.exceptions import ValidationError
from . import models
from django.conf import settings

#登录使用序列化类
class LoginSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['username','password']
        extra_kwargs={
            'password':{'write_only':True}
        }
    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        user = models.User.objects.filter(username=username).first()
        ret = user.check_password(password)
        if ret:
            # 签发token
            token = self._get_token(username)
            # 放到context中，在视图类中可以使用,ser.context.get('token')中能够获取到
            self.context['token'] = token
            self.context['user'] = user
            return attrs
        else:
            raise ValidationError('用户名或密码错误')
    def _get_token(self,username):
        from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
        payload = jwt_payload_handler(username)
        token = jwt_encode_handler(payload)
        return token

#老师学生信息的序列化,被展示个人信息、同班同学信息、班导师信息
'''学生个人信息接口、老师个人信息接口、管理员查看学生信息接口、管理员查看老师信息接口 '''
class StudentsSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    username = serializers.CharField()
    sex =serializers.CharField(source='get_sex_display')
    name = serializers.CharField()
    telephone = serializers.CharField()
    email = serializers.EmailField()
    theclass = serializers.CharField(source='stuclass.classon')
    sid = serializers.CharField()
    icon = serializers.ImageField()
    role = serializers.CharField(source='get_role_display')
    profession = serializers.CharField(source='stuclass.profession.pname')
    college = serializers.CharField(source='stuclass.profession.college.collegename')

#将学生信息转成excel表需要的序列化器
class StudentsExcelServializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields =['name','username','telephone','email','sid','class_name','sex_name']

#修改密码的序列化器
class StuPasswordSerializer(serializers.ModelSerializer):
    #确认密码在数据库表中没有，需要写一个
    comfirepassword = serializers.CharField()
    #username是唯一标识，需要覆盖
    username = serializers.CharField()
    class Meta:
        model = models.User
        fields = ['username','password','comfirepassword']
        extra_kwargs = {
            'password':{'write_only':True},
        }
    def validate(self, attrs):
        #视图函数在是实例化序列化类对象的时候，将request传递给context字典
        request=self.context.get('request')
        if request:
            username = request.user
            # 判断当前登录的用户是否是传递过来的用户
            if username==attrs.get('username'):
                password = attrs.get('password')
                comfirepassword = attrs.get('comfirepassword')
                #两次密码是否一致
                if password==comfirepassword:
                    return attrs
                else:
                    raise ValidationError('密码不一致')
            else:
                raise ValidationError('修改的密码用户非当前登录用户')
        raise ValidationError('请求方式错误')

#找回密码的序列化器
class FindPasswordSerializer(serializers.ModelSerializer):
    #确认密码在数据库表中没有，需要写一个
    comfirepassword = serializers.CharField()
    #username是唯一标识，需要覆盖
    username = serializers.CharField()
    #验证码在用户表中没有，需要些一个字段
    code = serializers.CharField()
    class Meta:
        model = models.User
        fields = ['username','password','comfirepassword','code']
        extra_kwargs = {
            'password':{'write_only':True},
            'code':{'write_only':True},
            'comfirepassword':{'write_only':True},
        }
    def validate(self, attrs):
        redis = self.context['redis']
        username = attrs.get('username')
        user_code = attrs.get('code')
        #EMAILTITLE就是一个字符串前缀,保证key的复杂度
        redis_code = redis.get(settings.EMAILTITLE+username)
        if redis_code:
            redis_code=redis_code.decode('utf-8')
        password = attrs.get('password')
        comfirepassword=attrs.get('comfirepassword')
        if password==comfirepassword:
            if user_code==redis_code:
                user=models.User.objects.get(username=username)
                #修改密码
                user.set_password(password)
                user.save()
                return attrs
            raise ValidationError('验证码错误！！')
        raise ValidationError('两次输入的密码不一致！！')

#创建用户的序列化器
class CreateUser(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['username','password','email','telephone','name','sid','sex','role','entrance','stuclass_id']
        extra_kwargs = {
            'password':{'write_only':True}
        }
    def validate(self, attrs):
        request = self.context.get('request')
        user = models.User.objects.get(id=request.auth.get('id'))
        if user.role in [1,2]:
            return attrs
        raise ValidationError('没有权限操作')

#管理员上传的文件，序列化器
class AdminFileSerializer(serializers.Serializer):
    filename = serializers.CharField()
    file = serializers.FileField()
    desc = serializers.CharField()
    id = serializers.IntegerField(read_only=True)
    def validate(self, attrs):
        request = self.context.get('request')
        file = attrs.get('file')
        filename = file.name
        filetype = filename.split('.')[-1]
        if filetype =='txt':
            username = request.user
            if username[:5]=='admin':
                return attrs
            else:
                raise ValidationError({'code':102,'errors':'非管理员用户不能上传该文件'})
        else:
            raise ValidationError({'error':'文件格式只支持txt','code':102})

class PrizeFileSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.PrizeFile
        fields='__all__'
        extra_kwargs={
            'id':{'read_only':True}
        }

#学生课程分数的序列化器
class StuCreditSerializer(serializers.Serializer):
    #课程分数的id
    id = serializers.IntegerField(read_only=True)
    #课程编码
    course = serializers.CharField(source='course.courseno')
    #课程名字
    coursename = serializers.CharField(source='course.coursename')
    #班级
    stuclass = serializers.CharField()
    #学生学号
    student = serializers.CharField(source='student.username')
    #分数
    credit = serializers.CharField(source='score')
    #学期
    semester = serializers.DateField(source='course.semester.semestername')

#学生课程分数序列化类
class ExcelCreditServerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Election
        fields=['coursename','score','username','name','get_class','semester','is_pass']

#奖学金的序列化类
class PrizeSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    #学号
    student = serializers.CharField(source='student.username')
    #等级
    level = serializers.CharField()
    #平均分
    allcourse = serializers.CharField()
    #学院
    college = serializers.CharField(source='college.collegename')
    #专业
    profession = serializers.CharField(source='profession.pname')
    #学期
    semester = serializers.CharField(source='semester.semestername')
    #班级
    stuclass = serializers.CharField(source='stuclass.classon')
    def validate(self, attrs):
        try:
            #判断携带的学期、专业、学院、班级是否有问题
            semester=models.Semester.objects.get(semestername=attrs.get('semester').get('semestername'))
            profession = models.Profession.objects.get(pname=attrs.get('profession').get('pname'))
            college = models.College.objects.get(collegename=attrs.get('college').get('collegename'))
            stuclass = models.stuClass.objects.get(classon=attrs.get('stuclass').get('classon'))
        except:
            raise ValidationError('携带的班级、学期、学院、专业有问题')
        flag=False
        try:
            username = attrs.get('student').get('username')
            #一个学期内：一个学院的学生只能有一个奖学金
            user=models.Prize.objects.get(student__username=username,semester_id=semester.id,college_id=college.id)
            flag=True
        except:
            pass
        if flag:
            raise ValidationError('记录已经存在了')
        if int(attrs.get('level')) in [1, 2, 3]:
            try:
                models.Prize.objects.create(stuclass_id=stuclass.id,college_id=college.id,profession_id=profession.id,semester_id=semester.id,level=attrs.get('level'),allcourse=attrs.get('allcourse'),student=models.User.objects.get(username=attrs.get('student').get('username')))
                return attrs
            except:
                raise ValidationError('创建失败，未知错误')
        else:
            raise ValidationError('奖学金没有此等级。')

#学期的展示，用于选择展示的是哪个学期的奖学金获奖情况
class SemesterSerializer(serializers.Serializer):
    semestername = serializers.CharField()
    id = serializers.IntegerField(read_only=True)
    #后面，学期是在管理员哪里创建的，创建时不需要用到id

#课程详细表的序列化器
class CurricuSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Curriculum
        fields = '__all__'
        extra_kwargs={
            'id':{'read_only':True}
        }
    def validate(self, attrs):
        teacher = attrs.get('teacher')
        semester = attrs.get('semester')
        try:
            models.TeaProfession.objects.get(teacher_id=teacher.id)
        except:
            raise ValidationError('携带数据有误')
        models.Curriculum.objects.create(**attrs)
        return attrs
#用于详细课程的序列化
class ShowCurriSerializer(serializers.Serializer):
    id=serializers.IntegerField(read_only=True)
    teachtime = serializers.CharField()
    studytime = serializers.CharField()
    location = serializers.CharField()
    course = serializers.CharField(source='course.coursename')
    semester = serializers.CharField(source='semester.semestername')
    teacher = serializers.CharField(source='teacher.name')
    stuclass = serializers.CharField(source='stuclass.classon')
    howlong = serializers.CharField(source='course.active_time')





#班级信息的序列化器
class ClassSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.stuClass
        fields = '__all__'
        extra_kwargs={
            'id':{'read_only':True},

        }
    def validate(self, attrs):
        classon = attrs.get('classon')
        profession = attrs.get('profession')

        stuclass = models.stuClass.objects.filter(classon=classon)
        if classon.isalnum():
            if not stuclass:
                if profession:
                    return attrs
            raise ValidationError('班级已经存在')
        raise ValidationError('班级只能"200722"这种数字组成')
#专业的序列化器
class ProfessionSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Profession
        fields = '__all__'
        extra_kwargs={
            'id':{'read_only':True}
        }
    def validate(self, attrs):
        pno=attrs.get('pno')
        pname = attrs.get('pname')
        college = attrs.get('college')
        if not college:
            raise ValidationError('没有传递学院id')
        #attrs中如果是外键字段，直接拿到数据对象，而不是id，如果该表中没有该外键会自己报错的
        pro = models.Profession.objects.filter(Q(pno=pno)|Q(pname=pname))
        if not pro:
            models.Profession.objects.create(**attrs)
            return attrs
        raise ValidationError('专业编号或专业名已经存在了。')
#学院的序列化器

class CollegeSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.College
        fields = '__all__'
        extra_kwargs={
            'id':{'read_only':True}
        }
    def validate(self, attrs):
        collegeno=attrs.get('collegeno')
        collegename=attrs.get('collegename')
        college = models.College.objects.filter(Q(collegename=collegename)|Q(collegeno=collegeno))
        if college:
            raise ValidationError('已经存在学院编号或学院名字了')
        else:
            models.College.objects.create(**attrs)
            return attrs


#统考申请表的序列化器
class UnifileExamSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    examtime = serializers.CharField(min_length=1)
    course = serializers.CharField(source='course.coursename')
    stuclass = serializers.CharField(source='stuclass.classon')
    teacher = serializers.CharField(source='teacher.username',read_only=True)
    location = serializers.CharField()
    status = serializers.IntegerField(label='申请审核的状态')
    relust = serializers.CharField()


#公告的序列化器
class MessegeSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.SchoolMessege
        fields='__all__'
        extra_kwargs = {
            'id':{'read_only':True}
        }

#课程的序列化器
class CourseSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Course
        fields ='__all__'
        extra_kwargs={
            'studyhour': {'write_only': True},
            'credit': {'write_only': True},
            'profession': {'write_only': True},
            'semester': {'write_only': True},
            'id':{'read_only':True}

        }
    def validate(self, attrs):
        courseno=attrs.get('courseno')
        try:
            is_exist=models.Course.objects.filter(courseno=courseno)
        except:
            raise ValidationError('未携带课程id')
        if not is_exist:
            models.Course.objects.create(**attrs)
            return attrs
        raise ValidationError('课程id已经存在，不能重复')

class CoureseCreServserializer(serializers.ModelSerializer):
    class Meta:
        model = models.Course
        fields="__all__"
    def validate(self, attrs):
        print(attrs,8989898)
        return attrs

#老师录入学生信息时，看到的学生学号
class StudentUsernameSerializer(serializers.Serializer):
    username = serializers.CharField()
    id = serializers.IntegerField()

#老师与老师id，增加课程详细表时需要
class TeacherSerializer(serializers.Serializer):
    username = serializers.CharField(source='teacher.username')
    id = serializers.IntegerField(source='teacher.id')

import re
#修改个人信息的序列化类
class ChangeSelfServerializer(serializers.ModelSerializer):
    class Meta:
        #sex是0或1，代表女或男
        sex = serializers.IntegerField(source='sex')
        model = models.User
        fields=["sex",'name','telephone','email','sid']
        extra_kwargs={
        'telephone':{'max_length':11,'min_length':11}
        }
    def validate(self, attrs):
        email = attrs.get('email')
        result = re.findall( r'^(\w)+(.\w+)*@(\w)+((.\w+)+)$',email)
        if not result:
            raise ValidationError('邮箱格式错误')
        return attrs

#选修课的反序列化器
class ChoiceCourseServerializer(serializers.ModelSerializer):
    teacher = serializers.CharField(source='teacher.name')
    college = serializers.CharField(source='college.collegename')
    semster = serializers.CharField(source='semster.semestername')
    is_pass = serializers.CharField(source='get_is_pass_display')
    class Meta:
        model=models.ChoiceCourse
        # fields = ['courseid','coursename','teacher','college','students','semster']
        fields="__all__"
        extra_kwargs={
            'is_pass':{'required':False},
            'why':{'required':False},
            'new_count':{'required':False},
            'teacher':{'required':False},
            'college':{'required':False},
        }
    def validate(self, attrs):
        courseid=attrs.get('courseid')
        course = models.ChoiceCourse.objects.filter(courseid=courseid)
        if not course:
            return attrs
        raise ValidationError('课程编号已经存在，无法创建')

#选修课记录使用的序列化类
class ChoiceCourseShowServerializer(serializers.ModelSerializer):
    course = ChoiceCourseServerializer()
    username = serializers.CharField(source='student.username')
    this_id = serializers.IntegerField(source='id')
    class Meta:
        model = models.StudentChoiceCourse
        fields = ['username','this_id','course']

#学生查看选修课的上课具体时间
class StuChoiceCourseView(serializers.ModelSerializer):
    teachtime = serializers.CharField(source='section')
    studytime = serializers.IntegerField(source='days')
    howlong= serializers.CharField(source='weeks')
    semester = serializers.CharField(source='course.semster.semestername')
    course = serializers.CharField(source='course.coursename')
    teacher = serializers.CharField(source='course.teacher.name')
    class Meta:
        model = models.ChoiceCourseStudy
        fields = ['id','location','teachtime','studytime','howlong','semester','course','teacher']
        extra_kwargs={
            'id':{'read_only':True}
        }

#老师管理员查看班级信息的excel表格
class TeaShowStuMsgServerializer(serializers.ModelSerializer):
    class Meta:
        model = models.StudentMessageExcel
        fields=['id','username','file_path','filename','create_time']
        extra_kwargs={'id':{'read_only':True}}
#老师管理员查看学生课程成绩的excel表格

class TeaShowCreditServerializer(serializers.ModelSerializer):
    class Meta:
        model = models.StudentCreditExcel
        fields = ['id','username','file_path','filename','create_time']
        extra_kwargs = {
            'id':{'read_only':True}
        }
class ProfessionCreditServerializer(serializers.ModelSerializer):
    class Meta:
        model = models.ProfessionCreditExcel
        fields = ['id','username','file_path','filename','create_time']
        extra_kwargs = {
            'id':{'read_only':True}
        }
